/*
 * Copyright (c) 2009 Frederic Daoud
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package org.stripesbook.rayures.service.impl;

import static net.sourceforge.stripes.localization.DefaultLocalizationBundleFactory.BUNDLE_NAME;
import static net.sourceforge.stripes.localization.DefaultLocalizationBundleFactory.ERROR_MESSAGE_BUNDLE;
import static net.sourceforge.stripes.localization.DefaultLocalizationBundleFactory.FIELD_NAME_BUNDLE;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.config.BootstrapPropertyResolver;
import net.sourceforge.stripes.config.ConfigurableComponent;
import net.sourceforge.stripes.config.Configuration;
import net.sourceforge.stripes.controller.StripesFilter;
import net.sourceforge.stripes.localization.LocalizationBundleFactory;
import net.sourceforge.stripes.util.Log;
import org.stripesbook.rayures.service.LookupStrategy;
import org.stripesbook.rayures.service.ResourceBundleResolver;
import org.stripesbook.rayures.util.Location;
import org.stripesbook.rayures.util.MapBundle;
import org.stripesbook.rayures.util.Resolver;

public class ResourceBundleResolverImpl implements ResourceBundleResolver, ConfigurableComponent {
  private static final Log log = Log.getInstance(ResourceBundleResolverImpl.class);

  private LookupStrategy lookupStrategy;
  private String errorBundleName;
  private String fieldBundleName;

  public void init(Configuration config) throws Exception {
    lookupStrategy = Resolver.resolve(config, LookupStrategy.class);

    BootstrapPropertyResolver resolver = config.getBootstrapPropertyResolver();

    errorBundleName = resolver.getProperty(ERROR_MESSAGE_BUNDLE);

    if (errorBundleName == null) {
      this.errorBundleName = BUNDLE_NAME;
    }

    fieldBundleName = resolver.getProperty(FIELD_NAME_BUNDLE);

    if (this.fieldBundleName == null) {
      fieldBundleName = BUNDLE_NAME;
    }
  }

  public MapBundle resolveResourceBundles(Locale locale, ActionBean actionBean,
    String eventName)
  {
    MapBundle bundleMap = new MapBundle();

    // Add the default Stripes resource bundles
    LocalizationBundleFactory bundleFactory = StripesFilter.getConfiguration()
      .getLocalizationBundleFactory();

    ResourceBundle errorBundle = bundleFactory.getErrorMessageBundle(locale);
    bundleMap.putAll(getBundleMap(errorBundle));

    ResourceBundle formFieldBundle = bundleFactory.getFormFieldBundle(locale);
    if (!formFieldBundle.equals(errorBundle)) {
      bundleMap.putAll(getBundleMap(formFieldBundle));
    }

    List<String> bundleNames = getBundleNames(actionBean, eventName);

    // Traverse the list in reverse order to preserve priority
    for (int i = bundleNames.size() - 1; i >= 0; i--) {
      bundleMap.putAll(getBundleMap(bundleNames.get(i), locale));
    }

    return bundleMap;
  }

  /**
   * Returns the list of bundle names, in order of priority.
   */
  public List<String> getBundleNames(ActionBean actionBean, String eventName) {
    List<String> bundleNames = new ArrayList<String>();

    for (Location location : lookupStrategy.getSearchLocations(actionBean, eventName)) {
      bundleNames.add(location.getClassPath(errorBundleName, ""));
        
      if (!fieldBundleName.equals(errorBundleName)) {
        bundleNames.add(location.getClassPath(fieldBundleName, ""));
      }
    }
    return bundleNames;
  }

  public MapBundle getBundleMap(String bundleName, Locale locale) {
    log.debug("Looking for ", bundleName);

    try {
      ResourceBundle bundle = ResourceBundle.getBundle(bundleName, locale);
      log.debug("Added ", bundleName);
      return getBundleMap(bundle);
    }
    catch (MissingResourceException exc) {
      // deliberately ignore non-existent resource bundles
      log.trace("Could not find a bundle for ", bundleName);
      return new MapBundle();
    }
  }

  private MapBundle getBundleMap(ResourceBundle bundle) {
    MapBundle result = new MapBundle();
    for (String key : Collections.list(bundle.getKeys())) {
      result.put(key, bundle.getString(key));
    }
    return result;
  }
}
